package Syntax_Anlayzer;

import java.util.*;

public class ForecastAnalysisTable {
    public static Map<String, Map<String, List<String>>> forecastAnalysisTable = new HashMap<>();

    public void buildTable() {
        Iterator<String> iterator = Init.Production.keySet().iterator();
        while (iterator.hasNext()) {
            String leftSide = iterator.next();
            Set<List<String>> set = Init.Production.get(leftSide);
            Iterator<List<String>> itSet = set.iterator();
            while (itSet.hasNext()) {
                List<String> list = itSet.next();
                Set<String> first = new HashSet<>();
                boolean flag = false;
                Iterator<String> itList = list.listIterator();
                while (itList.hasNext()) {
                    String x = itList.next();
                    Set<String> myfirst = First.first.get(x);
                    if (myfirst.contains("$") == false) {
                        first.addAll(myfirst);
                        flag = true;
                        break;
                    }
                    first.addAll(myfirst);
                    first.remove("$");
                }
                if (flag == false) {
                    first.add("$");
                }
                Iterator<String> itset = first.iterator();
                while (itset.hasNext()) {
                    String a = itset.next();
                    if (a.equals("$")) continue;
                    if (Init.V_T.contains(a)) {
                        if (forecastAnalysisTable.containsKey(leftSide)) {
                            Map<String, List<String>> myMap = forecastAnalysisTable.get(leftSide);
                            List<String> mylist = new ArrayList<>();
                            mylist.addAll(list);
                            myMap.put(a, mylist);
                            forecastAnalysisTable.put(leftSide, myMap);
                        } else {
                            Map<String, List<String>> map = new HashMap<>();
                            map.put(a, list);
                            forecastAnalysisTable.put(leftSide, map);
                        }
                    }
                }
                if (first.contains("$")) {
                    Set<String> follow = Follow.follow.get(leftSide);
                    Iterator<String> followIter = follow.iterator();
                    while (followIter.hasNext()) {
                        String b = followIter.next();
                        if (forecastAnalysisTable.containsKey(leftSide)) {
                            Map<String, List<String>> myMap = forecastAnalysisTable.get(leftSide);
                            if (myMap.containsKey(b)) {
                                List<String> mylist = myMap.get(b);
                                if (!mylist.contains("$")) {
                                    mylist.add("$");
                                    myMap.put(b, mylist);
                                    forecastAnalysisTable.put(leftSide, myMap);
                                }
                            } else {
                                List<String> mylist = new ArrayList<>();
                                mylist.add("$");
                                myMap.put(b, mylist);
                                forecastAnalysisTable.put(leftSide, myMap);
                            }
                        } else {
                            Map<String, List<String>> map = new HashMap<>();
                            List<String> mylist = new ArrayList<>();
                            mylist.add("$");
                            map.put(b, mylist);
                            forecastAnalysisTable.put(leftSide, map);
                        }
                    }
                }
            }
        }

        // Ensure that the start symbol 'program' has an entry for '#'
        if (!forecastAnalysisTable.containsKey("program") || !forecastAnalysisTable.get("program").containsKey("#")) {
            Map<String, List<String>> programMap = forecastAnalysisTable.getOrDefault("program", new HashMap<>());
            List<String> emptyList = new ArrayList<>();
            emptyList.add("$"); // Representing the empty production
            programMap.put("#", emptyList);
            forecastAnalysisTable.put("program", programMap);
        }
    }
}